home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / CLESSONS.ZIP / LESSON9 < prev    next >
Text File  |  1986-02-08  |  21KB  |  395 lines

  1. .NT
  2.  A NOTE ABOUT THE LESSONS in C 
  3. .b4-24R5C4
  4. These were written while the author was ~Ilearning~N  the language and since
  5. .R6C4
  6. they  are  ~Ifree~N ( to  copy  and/or  distribute ) there  is  a money-back
  7. .R7C4
  8. guarantee on the accuracy of each and every statement in the lessons (!)
  9. .R9C4
  10. The  ~Idisplay~N  program was written ( in C ) in order to provide a vehicle
  11. .R10C4
  12. for displaying the lessons.
  13. .R12C5
  14. .B
  15. P.J.Ponzo
  16. .B
  17. Dept. of Applied Math
  18. .B
  19. Univ. of Waterloo
  20. .B
  21. Ontario N2L 3G1
  22. .K16,32
  23. PonzoTUTOR
  24. .WNT
  25.     the big SWITCH    
  26. .R5C1
  27.     You may recall, from an earlier lesson, that we checked various cases by
  28.     using the ~Iif-else if~N construction:
  29. 1 ~b~I         if ( such-and-such)    {     ~N
  30. 2 ~b~I              ----do this-----        ~N
  31. 3 ~b~I         }                            ~N
  32. 4 ~b~I         else if (this-or-that) {     ~N
  33. 5 ~b~I              ----do this-----        ~N
  34. 6 ~b~I         }                            ~N
  35. 7 ~b~I         else if ( whatever )   {     ~N
  36. 8 ~b~I              ----do this-----        ~N
  37. 9 ~b~I         }                            ~N
  38. 10~b~I         else {                       ~N
  39. 11~b~I              ----do this-----        ~N
  40. 12~b~I         }                            ~N
  41. 13~b~I         ----continuation of program  ~N
  42. .R20C1
  43.     Realize that ~Ionly one~N of the statements 2, 5, 8, 11 will be 
  44.     executed, depending upon which of the conditions 1, 4, 7, 10 is satisfied
  45.     first. (If none of 1,4 or 7 are satisfied, then 10 ~IIS~N satisfied and
  46.     11 will be executed).
  47. .w
  48. .WR20C1
  49.                                                                               
  50.                                                                               
  51.                                                                               
  52.                                                                               
  53. .R20C1
  54.     Even if the conditions 1 ~Iand~N 4 ~Iand~N 7 are all satisfied, only 
  55.     statement(s) 2 will be executed, then the program will continue with
  56.     statement 13, etc.
  57. .WR20C1
  58.                                                                               
  59.                                                                               
  60.                                                                               
  61. .R20C1
  62.     (There's a MORAL here. To speed up execution, put the ~Imost probable~N
  63.      condition first ... then the program won't have to do so much checking).
  64. .WN
  65.  
  66.     But there's another (more natural) way of checking a number of cases in C.
  67.  
  68. .R5C1
  69. ~b~I     switch (x)  {       /* Begin the SWITCH on the integer x.   */  ~N
  70. ~b~I     case 1:             /* If x is the integer 1, then          */  ~N
  71. ~b~I          do this;       /*   execute this statement ...         */  ~N
  72. ~b~I          and this;      /*   and this too.                      */  ~N
  73. ~b~I     case 2:             /* If x is the integer 2, then          */  ~N
  74. ~b~I          do this;       /*   execute this statement ...         */  ~N
  75. ~b~I          and this;      /*   and this too.                      */  ~N
  76. ~b~I     case 3:             /* If x is the integer 3, then          */  ~N
  77. ~b~I          do this;       /*   execute this statement ...         */  ~N
  78. ~b~I          and this;      /*   and this too.                      */  ~N
  79. ~b~I          and this;      /*   and this too.                      */  ~N
  80. ~b~I          and this;      /*   and this too.                      */  ~N
  81. ~b~I     case 4:             /* If x is the integer 4, then          */  ~N
  82. ~b~I          do this;       /*   execute this statement ...         */  ~N
  83. ~b~I     default:            /* If x is none of the above, then      */  ~N
  84. ~b~I          do this;       /*   execute this statement ...         */  ~N
  85. ~b~I     }                                                               ~N
  86. .w
  87. .W
  88.     Notice the opening and closing brackets for the SWITCH!
  89. .R5C1
  90. ~b~I     switch (x)  ~F{~N
  91. .R21C1
  92. ~b~I     ~F}~N
  93. .WN
  94.     ... and here's a variation ...
  95. .R5C1
  96. 1 ~b~I     switch (x)  {       /* Begin the SWITCH on the integer x.   */  ~N
  97. 2 ~b~I     case 1:             /* If x is the integer 1, then          */  ~N
  98. 3 ~b~I     case 2:             /* If x is the integer 2, then          */  ~N
  99. 4 ~b~I     case 3:             /* If x is the integer 3, then          */  ~N
  100. 5 ~b~I          do this;       /*   execute this statement ...         */  ~N
  101. 6 ~b~I          and this;      /*   and this too.                      */  ~N
  102. 7 ~b~I          and this;      /*   and this too.                      */  ~N
  103. 8 ~b~I          and this;      /*   and this too.                      */  ~N
  104. 9 ~b~I     case 4:             /* If x is the integer 4, then          */  ~N
  105. 10~b~I          do this;       /*   execute this statement ...         */  ~N
  106. 11~b~I     default:            /* If x is none of the above, then      */  ~N
  107. 12~b~I          do this;       /*   execute this statement ...         */  ~N
  108. 13~b~I     }                                                               ~N
  109.     If the ~b~Iint~Neger ~b~Ix~N is equal to ~I1 or 2 or 3~N then statements
  110.     5 to 8 will be executed! (...so the SWITCH will NOT STOP with the first
  111.     case that is satisfied, but will check ALL SUBSEQUENT CASES!)
  112. .W
  113.     If you don't want that to happen, then you may terminate a case with
  114.     a ~Fbreak~N.
  115. .K5,32
  116.  a WHO ?
  117. .WN
  118. 1 ~b~I     switch (x)  {       /* Begin the SWITCH on the integer x.   */  ~N
  119. 2 ~b~I     case 1:             /* If x is the integer 1, then          */  ~N
  120. 3 ~b~I     case 2:             /* If x is the integer 2, then          */  ~N
  121. 4 ~b~I     case 3:             /* If x is the integer 3, then          */  ~N
  122. 5 ~b~I          do this;       /*   execute this statement ...         */  ~N
  123. 6 ~b~I          and this;      /*   and this too.                      */  ~N
  124. 7 ~b~I          and this;      /*   and this too.                      */  ~N
  125. 8 ~b~I          and this;      /*   and this too.                      */  ~N
  126. 9 ~b~I          ~Fbreak;~N~b~I         /*   and now BREAK OUT OF THE SWITCH!   */  ~N
  127. 10~b~I     case 4:             /* If x is the integer 4, then          */  ~N
  128. 11~b~I          do this;       /*   execute this statement ...         */  ~N
  129. 12~b~I     default:            /* If x is none of the above, then      */  ~N
  130. 13~b~I          do this;       /*   execute this statement ...         */  ~N
  131. 14~b~I     }                                                               ~N
  132.     Now, if ~b~Ix~N is a ~I1 or 2 or 3~N, the statements 5 to 8 will be 
  133.     executed and (because of the ~b~Ibreak;~N in line 9) we leave the SWITCH
  134.     and continue beyond line 14.
  135.     If, however ~b~Ix~N is a ~I4~N, then only the statement(s) for this case
  136.     are executed (line 11, in this example).
  137.     ~IOnly if all cases fail will the default statement(s) be executed~N
  138.     (for example, if ~b~Ix~N is a ~I6~N then statement 13 is executed).
  139. .WNT
  140.      more SWITCHing    
  141. .R4C1
  142.     You may switch on any type of variable (not just ~b~Iint~Negers).
  143.     For example you may have declared ~b~Ix~N to be a ~b~Ichar~N, so ...
  144. 1 ~b~I     switch (x)  {       /* Begin the SWITCH on the char x.      */  ~N
  145. 2 ~b~I     case 'A':           /* If x is the character 'A', then      */  ~N
  146. 3 ~b~I     case 'u':           /* If x is the character 'u', then      */  ~N
  147. 4 ~b~I     case '#':           /* If x is the character '#', then      */  ~N
  148. 5 ~b~I          do this;       /*   execute this statement ...         */  ~N
  149. 6 ~b~I          and this;      /*   and this too.                      */  ~N
  150. 7 ~b~I          and this;      /*   and this too.                      */  ~N
  151. 8 ~b~I          and this;      /*   and this too.                      */  ~N
  152. 9 ~b~I          break;         /*   and now BREAK OUT OF THE SWITCH!   */  ~N
  153.     Note that the ~Icase~N comparison must be consistent with the variable
  154.     type.
  155.     If ~b~Ix~N is an ~b~Iint~N   then you may use ~b~Icase 7:~N
  156.     If ~b~Ix~N is a  ~b~Ichar~N  then you may use ~b~Icase '+':~N
  157.     If ~b~Ix~N is a  ~b~Ifloat~N then you may use ~b~Icase -1.234:~N
  158. .W
  159.     Think of the ~Icase~N comparisons as being equivalent to:
  160.     ~b~I if (x==7)~N  or  ~b~Iif (x=='+')~N  or  ~b~I if (x==-1.234)~N  etc.
  161.  
  162.     ... ~Iand you may leave out the ~Idefault~N if you wish!~N
  163. .WNT
  164.     CALL BY VALUE  and  CALL BY REFERENCE  
  165.  
  166.  
  167.     We mentioned in an earlier lesson that a ~Ifunction call~N, in which you
  168.     pass certain parameters ( like ~b~Iaverage(a,b)~N ), gives to the function
  169.     ~Icopies~N of the parameters. The function may change these copies but
  170.     the "originals" won't be changed. This is CALL BY VALUE.
  171.  
  172.     You may, however, WANT to have a function change the originals. In this
  173.     case you must tell the function where, in memory, the "originals" live.
  174.     To do this you may pass the ~Iaddresses~N of the parameters ( or ~r~Ipointers~N
  175.     to the parameters). This is CALL BY REFERENCE.
  176.  
  177.     Knowing where the "original" parameters are, in memory, a function may
  178.     now modify them.
  179. .WN
  180.     Suppose you want to ~b~Iexchange()~N the values of two ~b~Ifloat~Ning
  181.     point numbers, say ~b~Ix~N and ~b~Iy~N, by calling upon a function
  182.     ~b~Iexchange()~N :
  183.  
  184. ~b~Iexchange(&x,&y);          /* call the function, give it addresses of x,y*/~N
  185.  
  186.     The exchange funtion may look like:
  187.  
  188. ~b~Iexchange(u,v)            /* this function exchanges two "floats".       */~N
  189. ~b~Ifloat *u, *v;            /* declare u and v as pointers to "floats".    */~N
  190. ~b~I{                        /* the opening bracket for exchange().         */~N
  191. ~b~I    float temp;          /* declare a temporary float.                  */~N
  192. ~b~I    temp=*u;             /* make it equal to "what u points to".        */~N
  193. ~b~I    *u=*v;               /* place the contents of v into u.             */~N
  194. ~b~I    *v=temp;             /* place the "temp"orary float into v.         */~N
  195. ~b~I    return;              /* return ... no need to return anything!      */~N
  196. ~b~I}                        /*    the floats have been exchanged !!        */~N
  197. .WN
  198.     You can try it out with:
  199. ~b~Imain()    {
  200. ~b~I     float x=1.23, y=4.56;         /* declare and define two floats     */~N
  201. ~b~I     printf("\nx=%f, y=%f",x,y);   /* printf their values.              */~N
  202. ~b~I     exchange(&x,&y);              /* call the exchange program.        */~N
  203. ~b~I     printf("\nx=%f, y=%f",x,y);   /* printf their values again!        */~N
  204. ~b~I}                                  /* that's the end of main().         */~N
  205. ~b~Iexchange(u,v)            /* this function exchanges two "floats".       */~N
  206. ~b~Ifloat *u, *v;            /* declare u and v as pointers to "floats".    */~N
  207. ~b~I{                        /* the opening bracket for exchange().         */~N
  208. ~b~I    float temp;          /* declare a temporary float.                  */~N
  209. ~b~I    temp=*u;             /* make it equal to "what u points to".        */~N
  210. ~b~I    *u=*v;               /* place the contents of v into u.             */~N
  211. ~b~I    *v=temp;             /* place the "temp"orary float into v.         */~N
  212. ~b~I    return;              /* return ... no need to return anything!      */~N
  213. ~b~I}                        /*    the floats have been exchanged !!        */~N
  214.     Now exit the text editor, saving the above with the name ~Isam.c~N, then
  215.     compile using ~Icc sam~N, then link using ~Ilink sam~N, then execute via:
  216.     ~Isam~N, and get:
  217. ~r~Ix=1.230000, y=4.560000~N
  218. ~r~Ix=4.560000, y=1.230000~N
  219. .WK10,60
  220.  LOVELY!
  221. .WN
  222.     Here's the ~b~Iexchange()~N function again:
  223.  
  224. ~b~Iexchange(u,v)            /* this function exchanges two "floats".       */~N
  225. ~b~Ifloat *u, *v;            /* declare u and v as pointers to "floats".    */~N
  226. ~b~I{                        /* the opening bracket for exchange().         */~N
  227. ~b~I    float temp;          /* declare a temporary float.                  */~N
  228. ~b~I    temp=*u;             /* make it equal to "what u points to".        */~N
  229. ~b~I    *u=*v;               /* place the contents of v into u.             */~N
  230. ~b~I    *v=temp;             /* place the "temp"orary float into v.         */~N
  231. ~b~I    return;              /* return ... no need to return anything!      */~N
  232. ~b~I}                        /*    the floats have been exchanged !!        */~N
  233.     Here's another variation:
  234. ~b~Iexchange(u,v)            /* this function exchanges two "floats"~F?~N~b~I       */~N
  235. ~b~Ifloat *u, *v;            /* declare u and v as pointers to "floats".    */~N
  236. ~b~I{                        /* the opening bracket for exchange().         */~N
  237. ~b~I    float *temp;         /* declare a temporary ~Fpointer~N~b~I.                */~N
  238. ~b~I    temp=u;              /* make it equal to the pointer "u".           */~N
  239. ~b~I    u=v;                 /* make "u" point to what "v" points to.       */~N
  240. ~b~I    v=temp;              /* make "v" point to what "temp" points to.    */~N
  241. ~b~I    return;              /* return ... no need to return anything!      */~N
  242. ~b~I}                        /*    the floats have been exchanged ~F?????~N~b~I     */~N
  243.     Why won't the latter function work???
  244. .WK6,32
  245. I give up!
  246. .WN
  247.  
  248. ~b~Iexchange(u,v)            ~V/* this function does NOT exchange floats!     */~N
  249. ~b~Ifloat *u, *v;            /* declare u and v as pointers to "floats".    */~N
  250. ~b~I{                        /* the opening bracket for exchange().         */~N
  251. ~b~I    float *temp;         /* declare a temporary pointer.                */~N
  252. ~b~I    temp=u;              /* make it equal to the pointer "u".           */~N
  253. ~b~I    u=v;                 /* make "u" point to what "v" points to.       */~N
  254. ~b~I    v=temp;              /* make "v" point to what "temp" points to.    */~N
  255. ~b~I    return;              /* return.                                     */~N
  256. ~b~I}                        ~V/*    the floats have not been exchanged!      */~N
  257.  
  258.     In this variation, the pointers ~b~Iu~N and ~b~Iv~N are ~Icopies~N and,
  259.     although this function does change these copies of the pointers, their 
  260.     contents do ~INOT~N change! ( so the ~b~Ifloat~Ns never do get exchanged! ).
  261. .WK16,32
  262.  BEWARE!
  263. .WNT
  264.    passing FUNCTIONS to FUNCTIONS   
  265. .R5C1
  266.     In an earlier lesson we computed the roots of some equation x=f(x),
  267.     with f(x)=2*sin(x).
  268.  
  269. 1 ~b~I    double x=1.0, y, e;       /* double precision  ! */ ~N
  270. 2 ~b~I    do  {                     /* start of the do-loop*/ ~N
  271. 3 ~b~I        y=2.0*sin(x);         /* calculate y         */ ~N
  272. 4 ~b~I        e=fabs(y-x);          /* calculate error     */ ~N
  273. 5 ~b~I        x=y;                  /* change x to y       */ ~N
  274. 6 ~b~I    }   while (e>.0000005);   /* end condition       */ ~N
  275. 7 ~b~I    printf("x-2sin(x)=%f when x=%f",e,x);               ~N
  276.     Now suppose we turn this piece of code into a function, ~b~Isolve()~N
  277.     which we call via:
  278.  
  279. ~b~Iroot=solve(f,x,e);~N
  280.  
  281.     where we pass to ~b~Isolve()~N the function ~b~If(x)~N, and some initial
  282.     guess of the root, namely ~b~Ix~N, and an error specification ~b~Ie~N.
  283.  
  284.     We expect ~b~Isolve(f,x,e)~N to return a root (which, naturally, we call
  285.     root!).
  286. .WN
  287.     We may write ~b~Isolve()~N like so:
  288.  
  289. 1 ~b~Ifloat solve(fcn,x,error)      /* returns a FLOAT!                */ ~N
  290. 2 ~b~Ifloat (*fcn)();               /*     !!!!!!!!!!!!!!!!!!!!!!!!!   */ ~N
  291. 3 ~b~Ifloat x, error;               /* x-value & error are floats.     */ ~N
  292. 4 ~b~I{                                                                   ~N
  293. 5 ~b~I    float y, e;               /* declares 2 floats.              */ ~N
  294. 6 ~b~I    do  {                     /* start of the do-loop.           */ ~N
  295. 7 ~b~I        y=(*fcn)(x);          /* calculates y.                   */ ~N
  296. 8 ~b~I        e=fabs(y-x);          /* calculate absolute value of y-x.*/ ~N
  297. 9 ~b~I        x=y;                  /* change x to y.                  */ ~N
  298. 10~b~I    }   while (e>error);      /* check error if e is too large.  */ ~N
  299. 11~b~I    return(x);                /* return x=root if e<=error.      */ ~N
  300. 12~b~I}                                                                   ~N
  301.  
  302.     Line 2 has the curious declaration of ~b~Ifcn()~N as a ~r~Ifunction pointer~N.
  303.     The ~b~I (*fcn) ~N says it's a pointer, and the ~b~I()~N says it points
  304.     to a function and the ~b~Ifloat~N says this fcn returns a ~Ifloat~N!
  305.     Note too, in line 7, that whereas ~b~Ifcn~N is a pointer, ~b~I*fcn~N ~IIS~N
  306.     the function! ( The parentheses are necessary ).
  307. .WN
  308. .R1C1
  309. ~b~Imain()    {
  310. ~b~I     float f1(), f2(), f3(), solve();        /* declare functions used.*/~N
  311. ~b~I     printf("\nA root of x=f1(x) is %f",     /* printf the root ...    */~N
  312. ~b~I         solve(f1,1,.00005));                /* solve x=f1(x).         */~N
  313. ~b~I     printf("\nA root of x=f2(x) is %f",     /* printf the root ...    */~N
  314. ~b~I         solve(f2,-1,.00005));               /* solve x=f2(x).         */~N
  315. ~b~I     printf("\nA root of x=f3(x) is %f",     /* printf the root ...    */~N
  316. ~b~I         solve(f3,2,.00005));                /* solve x=f3(x).         */~N
  317. ~b~I}                                                                        ~N
  318. ~b~Ifloat f1(x)                                                              ~N
  319. ~b~Ifloat x;                                                                 ~N
  320. ~b~I{  return(2.*sin(x)); }                      /* f1(x) = 2 sin(x)       */~N
  321. ~b~Ifloat f2(x)                                                              ~N
  322. ~b~Ifloat x;                                                                 ~N
  323. ~b~I{  return(2.-x/2.); }                        /* f2(x) = 2-x/2          */~N
  324. ~b~Ifloat f3(x)                                                              ~N
  325. ~b~Ifloat x;                                                                 ~N
  326. ~b~I{  return(1.+1./x); }                        /* f3(x) = 1+1/x          */~N
  327. .w
  328. .R2C1
  329. ~V     float f1(), f2(), f3(), solve();        /* declare functions used.*/~N
  330. .R19C1
  331.     Here we declare all the functions we use ( they all return a float).
  332. .WR2C1
  333. ~b~I     float f1(), f2(), f3(), solve();        /* declare functions used.*/~N
  334. ~V     printf("\nA root of x=f1(x) is %f",     /* printf the root ...    */~N
  335. ~V         solve(f1,1,.00005));                /* solve x=f1(x).         */~N
  336. .R19C1
  337.     Here we print (after a ~b~I\n~Newline) ~r~IA root of x=f1(x) is ~N              
  338.     followed by the ~b~I%f~Nloat ~Ireturned~N by solve(f1,1,.00005)~N.        
  339.     Note that we pass the ~Ipointer  f1~N, a starting value ~I1~N             
  340.     and an error specification of .00005                                      
  341. .WR3C1
  342. ~b~I     printf("\nA root of x=f1(x) is %f",     /* printf the root ...    */~N
  343. ~b~I         solve(f1,1,.00005));                /* solve x=f1(x).         */~N
  344. .R19C1
  345. .w
  346.     ... then we continue with two more functions f2(x) and f3(x), each time   
  347.     specifying not only the ~r~Ipointer~N to the function but also a starting 
  348.     value and error specification.                                            
  349.                                                                               
  350. .WN
  351. .R3C2
  352. REMEMBER: To pass the function ~b~Isam(a,b,c)~N as an argument to another
  353.  
  354.           function ~b~Igeorge(sam,x,y)~N, then include the declaration
  355.  
  356.           ~b~Ifloat (*sam)()~N ( make this declaration within ~b~Igeorge()~N )
  357.  
  358.           and use it ( within ~b~Igeorge()~N ) as ~b~I(*sam)(a,b,c)~N.
  359.  
  360.           If ~b~Isam()~N returns an ~b~Iint~N or ~b~Ichar~N then (of course)
  361.  
  362.           it should be declared as ~b~Iint (*sam)()~N or ~b~Ichar (*sam)()~N!
  363. .b2-14
  364. .K16,32
  365. mamma mia!
  366. .WN
  367.  
  368. ~r~IA root of x=f1(x) is 1.895475~N              Here's
  369. ~r~IA root of x=f2(x) is 1.333324~N               our
  370. ~r~IA root of x=f3(x) is 1.618026~N              output.
  371.  
  372.     and (because we use only ~Ifloat~N and not ~Idouble~N, and we gave
  373.     an error specification of .00005) we get (roughly) 4 decimal place
  374.     accuracy.
  375.  
  376. .W
  377.     Well, the programming ain't too sexy ( how useful are these 3 built-in
  378.     functions, f1(x), f2(x) and f3(x) ? ) and the mathematics is even worse
  379.     (you can't guarantee that the program won't get stuck in the ~b~Isolve()~N
  380.     function ... forever trying to reduce a growing error!), BUT ... we get
  381.     the idea ... right?
  382. .WK16,32
  383.  RIGHT!!  
  384. .WN
  385.  
  386.  
  387. .T
  388.    That's all folks!   
  389. .K16,32
  390. au revoir!
  391.  
  392.  
  393. .q
  394.  
  395.